home *** CD-ROM | disk | FTP | other *** search
- ////////////////////////////////////////////////////////////
- // Package node class implementation file
- // Copyright (c) 1991 by Azarona Software
- // All rights reserved.
- ////////////////////////////////////////////////////////////
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "pnode.h"
-
- //
- // Methods for the pnode allocator
- //
-
- pnode_allocator::pnode_allocator(int sz)
- // Allocate space for sz nodes
- {
- data = new anode[size = sz];
- if (data == 0) {
- printf("No room to allocate pnode storage\n");
- exit(1);
- }
-
- data->node_cnt = 0; // Keeps track of number of nodes used
- for (int i = 0; i<sz; i++) data[i].n = i+1; // Set up free list
- data[sz-1].n = 0;
- }
-
- void *pnode_allocator::alloc(void)
- // Grab a pnode from the free list
- {
- unsigned i = data->n; // Get free anode index
- if (i == 0) return 0; // No more room
- data->node_cnt++; // Keep track of used pnodes
- data->n = (data + i)->n; // Move head of free list
- return (void *)(data + i);
- }
-
- void pnode_allocator::free(void *p)
- // Put p at the head of the free list
- {
- ((anode *)p)->n = data->n;
- data->n = (unsigned(p) - unsigned(data)) / sizeof(anode);
- data->node_cnt--;
- }
-
- //
- // Methods for the pnode class
- //
-
- pnode *pnode::make_package(pnode *a, pnode *b)
- {
- pnode *p;
-
- pnode *c = new pnode(a->wt + b->wt, 0, -1, 0);
- if (c == 0) {
- printf("No room for combined pnode\n");
- exit(1);
- }
-
- // Now, merge a and b pnodes into to this package
-
- if (a->n == 0) { // a is a singleton
- c->n = a;
- if (b->lvl == -1) { // b is internal
- a->n = b->n; // so skip it
- delete b; // and dump it
- } else a->n = b;
- }
- else { // a is a package
- if (b->n == 0) { // b is a singleton
- c->n = b;
- if (a->lvl == -1) { // a is internal
- b->n = a->n; // so skip it
- delete a; // and dump it
- } else b->n = a;
- }
- else { // both a and b are packages
- if (a->lvl == -1) { // a is internal
- p = a->n; // so skip it
- delete a; // and dump it
- }
- else p = a;
- c->n = p;
- // find end a list
- while(p->n) p = p->n; // p guaranteed to be non-null
- if (b->lvl == -1) { // b is internal
- p->n = b->n; // so skip it
- delete b; // and dump it
- }
- else p->n = b;
- }
- }
-
- return c;
- }
-
- void pnode::rmv_package(pnode *p)
- // Delete all nodes in the package p
- {
- while(p) {
- pnode *q = p->n;
- delete p;
- p = q;
- }
- }
-
-
- pnode *nodeset::remove_front(void)
- {
- pnode *p = data[0];
- memmove(data, data+1, (cursor--)*sizeof(pnode *));
- return p;
- }
-
- //
- // Methods for the nodeset class
- //
-
- void nodeset::package(void)
- // Packages up the nodeset in place
- {
- int p = 0, q, nxtavl = 0;
- while(p<cursor) { // Have at least one pnode
- q = p+1;
- if (q<cursor) { // Have at least two pnodes, so make package
- data[nxtavl++] =
- pnode::make_package(data[p], data[q]);
- p += 2;
- }
- else {
- // Singleton node, so toss complete package
- pnode::rmv_package(data[p]);
- break;
- }
- }
- cursor = nxtavl; // New size of nodeset
- }
-
- void nodeset::setup_and_merge(nodeset &nset, long wts[],
- unsigned char smap[],
- int num_syms, int level)
- // ASSUMES LEVEL >= 0
- {
- int p = num_syms - 1;
- int q = 0; // Start at head of nset
- cursor = 0; // Start with an new empty nodeset
-
- while(1) {
- if (p >= 0) {
- if (q<nset.cursor) { // Dealing from both decks
- if (wts[p] <= nset.data[q]->wt) {
- pnode *baby = new pnode(wts[p], smap[p], level, 0);
- if (baby == 0) {
- printf("No room for new pnode\n");
- exit(1);
- }
- data[cursor++] = baby;
- p--;
- }
- else {
- data[cursor++] = nset.data[q++];
- }
- }
- else { // No more q left
- for (; p >= 0; p--) {
- pnode *baby = new pnode(wts[p], smap[p], level, 0);
- if (baby == 0) {
- printf("No room for new pnode\n");
- exit(1);
- }
- data[cursor++] = baby;
- }
- break;
- }
- }
- else { // No more p left, so copy rest of q;
- int num_pnodes = nset.cursor - q;
- memmove(data+cursor, nset.data+q, num_pnodes*sizeof(pnode *));
- cursor += num_pnodes;
- break;
- }
- }
- }
-